package com.wangwei.modules.utils.ann;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import com.wangwei.modules.utils.method.MethodUtil;
import com.wangwei.modules.utils.method.bean.MethodInfoVO;

public class AnnUtil {

    /**
     * 判断类是否有某个注解，包括他的父类
     * @param className
     * @param annotations
     * @return
     * @throws ClassNotFoundException 
     */
    public static boolean checkClassHasAnn(String className, Class<? extends Annotation> annotationClass) throws ClassNotFoundException {
        Class<?> clazz = Class.forName(className);
        return checkClassHasAnn(clazz, annotationClass);
    }

    /**
     * 判断类是否有某个注解，包括他的父类
     * @param clazz
     * @param annotationClass
     * @return
     * @throws ClassNotFoundException
     */
    public static boolean checkClassHasAnn(Class<?> clazz, Class<? extends Annotation> annotationClass) throws ClassNotFoundException {
        
        if (clazz.isAnnotation()||clazz.isInterface()) {
            return false;
        }
        
        Annotation[] anns = clazz.getAnnotations();
        for (Annotation annotation : anns) {
            if (checkAnnHasAnn(annotation.annotationType(), annotationClass,new HashSet<>())) {
                return true;
            }
        } 
        
        if (clazz.getAnnotation(annotationClass) != null) {
            return true;
        }else {
            //判断父类有没有
            Class<?> superClass = clazz.getSuperclass();
            if (superClass != null && !(superClass instanceof Object)) {
                return checkClassHasAnn(superClass, annotationClass);
            }
        }

        return false;
    }



    /**
     * 验证注解annotationClass是否带有注解checkAnnotationClass
     * @param annotationClass
     * @param checkAnnotationClass
     * @return
     * @throws ClassNotFoundException
     */
    public static boolean checkAnnHasAnn(Class<? extends Annotation> annotationClass, Class<? extends Annotation> checkAnnotationClass,HashSet<Class<? extends Annotation>> checkedClass) throws ClassNotFoundException {
        checkedClass.add(annotationClass);
        if (annotationClass.isAssignableFrom(checkAnnotationClass)) {
            return true;
        } else if (annotationClass.getAnnotationsByType(checkAnnotationClass).length !=0) {
            return true;
        } else {
            Annotation[] anns = annotationClass.getAnnotations();
            for (Annotation annotation : anns) {
                Class<? extends Annotation> clazz=annotation.annotationType();
                if ((!checkedClass.contains(clazz))&&checkAnnHasAnn(clazz, checkAnnotationClass,checkedClass)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 获取带有某些注解的方法详情
     * @param className
     * @param annotations
     * @return
     */
    public static List<MethodInfoVO> getAnnMethodInfo(String className, Class<? extends Annotation>... annotations) {
        List<MethodInfoVO> list = new ArrayList<>();
        try {
            Method[] methods = Class.forName(className).getDeclaredMethods();
            for (Method method : methods) {
                for (Class<? extends Annotation> annotation : annotations) {
                    if (method.isAnnotationPresent(annotation)) {
                        // 组装对象
                        MethodInfoVO methodInfoVO = MethodUtil.getMethodParamNames(method);
                        list.add(methodInfoVO);
                        System.out.println("servlet fun:" + methodInfoVO.getPath() + " " + methodInfoVO);
                    }
                }
            }
            return list;
        } catch (SecurityException e) {
            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }

    }
}
